www.gusucode.com > VC编写的串口调试软件 > VC编写的串口调试软件,内含Modbus协议类 支持对Modbus通讯调试/Modbus串口调试软件1.0/com/MsgPSPWnd.cpp
// MsgPumpWnd.cpp : implementation file // #include "stdafx.h" #include "MsgPSPWnd.h" #include "..\com\FOData.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CMsgPSPWnd CMsgPSPWnd::CMsgPSPWnd() { TRACE("CMsgPSPWnd--构造--0x%x\n",this); m_strAlias="串口通讯"; m_unMemFileSize=0; m_pThread=NULL; //线程 m_pProtocal=NULL; m_pSerialPort=NULL; m_pReData=NULL; m_pCurData=NULL; m_nCurPos=NULL; m_nNextPos=NULL; //下一条记录 m_bWriteValue=false; m_dwStartCalcTime=0; m_nRecieveState=1; //数据接收状态,1:正确,2:要求重发 m_unTimeRelay=1000; //延时ms m_unReSendNum=0; //重发次数 m_unCheckOtherCommTime=0; m_ucRcvTxt[0]='\n'; //接收缓冲区 m_unRcvLen=0; //接收长度 } UINT CMsgPSPWnd::m_unCommErr=0; //连续通讯错误 UINT CMsgPSPWnd::m_unCommErrCount=30; int CMsgPSPWnd::m_nCommErrTime=0; //错误计时 int CMsgPSPWnd::m_nCommErrTimeCount=120000; //错误计时数:如果在计时时段内通讯,当m_unCommErr>=m_unCommErrCount,则无需通讯重新开始 UINT CMsgPSPWnd::m_unCommSucceed=0; //连续通讯成功次数,如果连续通讯次数达到100次,则通讯错误清空 UINT CMsgPSPWnd::m_unCommSucceedCount=100; //100次,则通讯错误清空 CMsgPSPWnd::~CMsgPSPWnd() { TRACE("CMsgPSPWnd--析构--0x%x\n",this); ReleaseResource(); } BEGIN_MESSAGE_MAP(CMsgPSPWnd, CPlugPPBase) //{{AFX_MSG_MAP(CMsgPSPWnd) ON_MESSAGE(WM_COMM_RXCHAR, OnCommRXChar) ON_MESSAGE(WM_COMM_CTS_DETECTED, OnCommCTSDetected) ON_MESSAGE(WM_COMM_BREAK_DETECTED, OnCommBreadDetected) ON_MESSAGE(WM_COMM_DSR_DETECTED, OnCommDSRDetected) ON_MESSAGE(WM_COMM_ERR_DETECTED, OnCommERRDetected) ON_MESSAGE(WM_COMM_RING_DETECTED, OnCommRingDetected) ON_MESSAGE(WM_COMM_RXFLAG_DETECTED, OnCommRXFlagDetected) ON_MESSAGE(WM_COMM_TXEMPTY_DETECTED, OnCommTXEmptyDetected) ON_MESSAGE(WM_COMM_RLSD_DETECTED, OnCommRLSDDected) ON_WM_TIMER() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CMsgPSPWnd message handlers CComData CMsgPSPWnd::GetData(const POSITION& pos) { CComData* pComData=(CComData*)m_listData.GetAt(pos); return *pComData; } CString CMsgPSPWnd::GetProtocalName() { CreateProtocal(); if(m_pProtocal) return m_pProtocal->m_strPrtName; // strcpy((LPTSTR)(LPCTSTR)rString,(LPTSTR)(LPCTSTR)m_pProtocal->m_strPrtName); // else // strcpy((LPTSTR)(LPCTSTR)rString,"无"); CString str="未知协议"; return str; } CString CMsgPSPWnd::GetValue(const POSITION &pos) { CComData* pComData=(CComData*)m_listData.GetAt(pos); return pComData->m_strRegValue; } void CMsgPSPWnd::Release() { TRACE("\n**********协议驱动:%s\n","ModBus"); try{ delete this; }catch(...) { TRACE("\n*****CMsgPSPWnd::Release()\n"); } } BOOL CMsgPSPWnd::Run (HWND hWndParent) { CString strInfo="I CMsgPSPWnd"; //1、连接协议 CreateProtocal(); if (NULL==m_pProtocal) { strInfo.Format ("协议%s创建失败",m_pProtocal->m_strPrtName); CWnd wnd; wnd.Attach (hWndParent); wnd.SendMessage(WM_SEND_RECEIVE,WPARAM('I'),LPARAM(&strInfo)); //不能用邮寄方式PostMessage wnd.Detach (); return FALSE; } //2、创建窗口 ASSERT(NULL==m_hWnd); //已经被调用过一次 BOOL bT=CreateEx(0, //dwExStyle //---方法2 AfxRegisterWndClass(0), //lpszClassName NULL, //lpszWindowName WS_CHILD,//WS_POPUP,WS_BORDER|WS_POPUP, //dwStyle 0,0,0,0, hWndParent, //hwndParent 0); //nIDorHMenu // return bT; if (FALSE==bT) { TRACE("*********** CMsgPSPWnd--窗口创建失败 %s *********\n",m_strAlias); strInfo.Format ("%s--窗口创建失败",m_pProtocal->m_strPrtName); CWnd wnd; wnd.Attach (hWndParent); wnd.SendMessage(WM_SEND_RECEIVE,WPARAM('I'),LPARAM(&strInfo)); //不能用邮寄方式PostMessage wnd.Detach (); delete m_pProtocal; return bT; } //3、创建端口 m_pSerialPort=new CSerialPort; if(NULL==m_pSerialPort) return FALSE; //读取端口设定信息 ReadPortInf(); if( m_pSerialPort->InitPort(this, m_SPData.uPortNum, m_SPData.uBaud, m_SPData.cParity, m_SPData.uDataBits, m_SPData.uStopBits, m_SPData.dwCommEvents, m_SPData.nBufferSize)) { strInfo.Format ("%s打开端口%d",m_pProtocal->m_strPrtName,m_SPData.uPortNum); GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('I'),LPARAM(&strInfo) ); m_pSerialPort->StartMonitoring(); TRACE("*********** FIND PORT %d *********0x%x\n",m_SPData.uPortNum,m_pSerialPort); } else { strInfo.Format ("%s打开端口%d失败",m_pProtocal->m_strPrtName,m_SPData.uPortNum); GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('I'),LPARAM(&strInfo) ); // port not found TRACE("***********NO FIND PORT %d *********\n",m_SPData.uPortNum); delete m_pProtocal; return FALSE; } //4、读取数据 ReadIO(); strInfo.Format ("%s加载数据成功",m_pProtocal->m_strPrtName,m_SPData.uPortNum); GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('I'),LPARAM(&strInfo) ); //5、创建内存文件 CreateMemFile(); SetTimer(TIMER_EVENT_WM,500,NULL); //5、启动线程 if (!(m_pThread = AfxBeginThread(RunPump,this))) { delete m_pProtocal; return FALSE; } strInfo.Format ("%s启动数据通讯",m_pProtocal->m_strPrtName); GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('I'),LPARAM(&strInfo) ); return bT; } UINT CMsgPSPWnd::RunPump (LPVOID pParam ) { //先休眠2s,便于程序启动完毕 // ::Sleep (2000); CMsgPSPWnd* pMsgPump=(CMsgPSPWnd*) pParam; if(NULL==pMsgPump->m_pProtocal) {TRACE("CMsgPSPWnd::RunPump()----通信协议未指定! \n");} //1、得到首记录 pMsgPump->m_nNextPos=pMsgPump->m_listData.GetHeadPosition(); if(NULL==pMsgPump->m_nNextPos) return 1; //没有记录 try { while(pMsgPump) { //----------------------------------------------------------------------------------------------------------------------------- //1、检查是否需要等待发送-------时间轮片机制(多主站协议)----2003.12.21 if(pMsgPump->IsWaitSend()) continue; //---------------------------------------------------------------- //2、超时处理 if(pMsgPump->m_pCurData) { if(pMsgPump->m_unTimeRelay<=pMsgPump->GetCalcTime() //通讯超时 && 0==pMsgPump->m_nRecieveState) { //发送一个超时消息 //发送已经接收到的信息 if(0<pMsgPump->m_pCurData->m_unRcvLen ) pMsgPump->GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('c'),LPARAM(&pMsgPump->GetRevInfo()) ); // if(2>pMsgPump->m_unReSendNum++) { pMsgPump->m_unCommSucceed=0; //* TRACE("CMsgPSPWnd::RunPump 超时重发=%d\t寄存器类型:% 6d\t寄存器地址:% 6d\t协议类型:\n", pMsgPump->m_unReSendNum,pMsgPump->m_pCurData->m_unRegType,pMsgPump->m_pCurData->m_unRegAddr); TRACE("CMsgPSPWnd::RunPump 超时%d\t延时%d\t%d\n",pMsgPump->GetCalcTime(),pMsgPump->m_unTimeRelay,::GetTickCount()); //*/ //重发清除以前接收到的数据m_CurData.ClearRData(); //协议接收状态为等待状态 pMsgPump->m_pProtocal->Init (); if(pMsgPump->m_bWriteValue) { pMsgPump->GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('W'),LPARAM(&pMsgPump->GetSendInfo()) ); } else pMsgPump->GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('R'),LPARAM(&pMsgPump->GetSendInfo()) ); pMsgPump->m_pSerialPort->WriteToPort (pMsgPump->m_pCurData->m_ucProtocalTxt,pMsgPump->m_pCurData->m_unDataLen ); pMsgPump->StartCalcTime (); } else //多次从发后仍通讯失败 { //恢复上次数据 if(pMsgPump->m_pCurData->m_hClientWnd) //写操作 { //--------------------------------------------------------------------------------------------------------- //回传数据 char cInfo[100]; CString strInfo; sprintf(cInfo,"%s %s", pMsgPump->m_pCurData->m_strAlias,COM_WRTIE_FALSE); //--------------------------------------------------------------------------------------------------------- COPYDATASTRUCT CpyData; CpyData.lpData =&cInfo[0]; CpyData.cbData =sizeof(cInfo)/sizeof(char); WPARAM wParam = (WPARAM) (HWND)pMsgPump->m_hWnd ; // handle of sending window LPARAM lParam = (LPARAM) & CpyData; // pointer to structure with data CWnd wnd; wnd.Attach (pMsgPump->m_pCurData->m_hClientWnd); wnd.SendMessage(WM_COPYDATA,wParam,lParam); //不能用邮寄方式PostMessage wnd.Detach (); } //发送下一条信息试试 pMsgPump->m_unReSendNum=0; //重发次数 pMsgPump->m_nRecieveState=1; } //可能系统通讯中断比较长或通讯失败较多,则重新建立通讯 if(IsMoreCommErr()) { pMsgPump->SetTimer(1,3000,NULL); return 1; } } } //---------------------------------------------------------------- //3、发送处理 switch(pMsgPump->m_nRecieveState) { case 0: //正在接收记录 break; case 1: //上一条数据接收完毕,发送新数据 IsMoreSucceed(); //多次通讯成功,清空计时错误 pMsgPump->m_unReSendNum=0; //重发次数 //一、检查有无需要立即发送的数据----如果写数据失败,没有处理,因该再恢复原值? if(pMsgPump->m_pReData) { //说明上次进行了写操作,将写操作相关寄存器的值对应的数据读取一遍,可以加快刷新速度 pMsgPump->m_pCurData=pMsgPump->m_pReData; pMsgPump->m_pReData=NULL; pMsgPump->m_bWriteValue =false; } else { if(NULL!=pMsgPump->m_listNowData.GetHeadPosition()) { pMsgPump->m_pCurData=(CComData*)pMsgPump->m_listNowData.RemoveHead (); pMsgPump->m_bWriteValue =true; } else {//发送读取记录信息 int nGood=0; int nPriority=0; do{ if(NULL==pMsgPump->m_nNextPos) { //更新数据 pMsgPump->WriteMemData(); // pMsgPump->m_nNextPos=pMsgPump->m_listData.GetHeadPosition(); if(100<++pMsgPump->m_unCycleTime) //循环次数 pMsgPump->m_unCycleTime=1; if(nGood++>2) break; //说明没有发送的数据,可能完全写操作 } pMsgPump->m_nCurPos=pMsgPump->m_nNextPos; pMsgPump->m_pCurData=(CComData*)pMsgPump->m_listData.GetNext (pMsgPump->m_nNextPos); nPriority=pMsgPump->m_pCurData->m_unPriority; nPriority=nPriority==0?5:nPriority; }while(pMsgPump->m_unCycleTime%nPriority!=0 && pMsgPump->m_unCycleTime>3 ); pMsgPump->m_bWriteValue =false; } } //二、发送新数据 //1、得到数据 //2、翻译数据 ::Sleep (10); //翻译通讯协议 pMsgPump->m_pProtocal->Decoding(*pMsgPump->m_pCurData); case 2: //再发送一次//协议接收状态为等待状态 case 3: //校验错误,要求重发一次//协议接收状态为等待状态 if(pMsgPump->m_bWriteValue) pMsgPump->GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('W'),LPARAM(&pMsgPump->GetSendInfo()) ); else pMsgPump->GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('R'),LPARAM(&pMsgPump->GetSendInfo()) ); pMsgPump->m_pProtocal->Init (); pMsgPump->m_pSerialPort->WriteToPort (pMsgPump->m_pCurData->m_ucProtocalTxt,pMsgPump->m_pCurData->m_unDataLen ); pMsgPump->m_nRecieveState=0; pMsgPump->StartCalcTime (); break; default: TRACE("CMsgPSPWnd::RunPump()----接收状态错误! \n"); pMsgPump->m_nRecieveState=1; break; } } //while } catch(CString strEx) { CString strErr; strErr.Format ("RumPump()--%s:%s",pMsgPump->m_strAlias,strEx); pMsgPump->GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('E'),LPARAM(&strErr) ); TRACE("%s\n",strEx); } catch(char* szException) { CString strErr; strErr.Format ("RumPump()--%s:%s",pMsgPump->m_strAlias,szException); pMsgPump->GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('E'),LPARAM(&strErr) ); TRACE("%s\n",szException); } catch(...) { CString strErr; strErr.Format ("RumPump()--%s:发生不知道的错误!",pMsgPump->m_strAlias); pMsgPump->GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('E'),LPARAM(&strErr) ); TRACE("CMsgPSPWnd::RunPump()----发生不知道的错误! \n"); } //退出线程 pMsgPump->m_pThread=NULL; return 1; } // A character was received and placed in the input buffer. LONG CMsgPSPWnd::OnCommRXChar(WPARAM ch, LPARAM port) { if (port <= 0 || port > 4) return -1; if (NULL==m_pProtocal) { TRACE("<*>*<*>*<*> m_pProtocal==NULL\n"); return -1; } try { CString strValue; m_ucRcvTxt[m_unRcvLen++]=ch; //接收缓冲区 int nReceiveState=m_pProtocal->ReceiveByte ((unsigned char&) ch); switch(nReceiveState) { case 0: { //正在接收 break; } case 1: { //字符接收完毕 m_nRecieveState=1; //更新旧值 m_pCurData->m_strOldRegValue =m_pCurData->m_strRegValue ; #ifdef _DEBUG // if(m_bWriteValue) TRACE("RegAddr=%d RegValue=%s\n",m_pCurData->m_unRegAddr,m_pCurData->m_strRegValue); #endif //将当前结果存放在列表中 GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('C'),LPARAM(&GetRevInfo()) ); m_unRcvLen=0; //写操作 if(m_pCurData->m_hClientWnd) { char cInfo[100]; CString strInfo; sprintf(cInfo,"%s %s", m_pCurData->m_strAlias ,m_pCurData->m_strRegValue); COPYDATASTRUCT CpyData; CpyData.lpData =&cInfo[0]; CpyData.cbData =sizeof(cInfo)/sizeof(char); WPARAM wParam = (WPARAM) (HWND) m_hWnd ; // handle of sending window LPARAM lParam = (LPARAM) & CpyData; // pointer to structure with data CWnd wnd; wnd.Attach (m_pCurData->m_hClientWnd); wnd.SendMessage(WM_COPYDATA,wParam,lParam); //不能用邮寄方式PostMessage wnd.Detach (); // //写成功 //--------------------------------------------------------------------------------------------------------- m_pReData=m_pCurData->m_pReData; delete m_pCurData; m_pCurData=NULL; m_bWriteValue=false; //--------------------------------------------------------------------------------------------------------- } if (0<m_pCurData->m_unReSend) m_nRecieveState=2; //通讯连接正常 m_unCommErr=0; // TRACE("CMsgPSPWnd::OnCommRXChar()----接收状态正确! 寄存器类型:%s\t地址:%s=%s\n", // m_CurData.m_strRegType,m_CurData.m_strRegAddr,m_CurData.m_strRegValue ); break; } case 2: //是否要重发,由协议自己处理 { //要求重发送一次 GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('c'),LPARAM(&GetRevInfo()) ); m_unRcvLen=0; break; } case 4: //数据项为空,可能有其他设备在通讯 { // GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('C'),LPARAM(&GetRevInfo()) ); m_unRcvLen=0; int nTime=m_unCheckOtherCommTime; m_unCheckOtherCommTime=::GetTickCount(); // TRACE("CMsgPSPWnd::OnCommRXChar()--%d-时间间隔:%d-其他设备在通讯! \n",m_unCheckOtherCommTime,m_unCheckOtherCommTime-nTime); break; } default: //不知道的信息 { TRACE("CMsgPSPWnd::OnCommRXChar()----接收状态错误! \n"); GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('c'),LPARAM(&GetRevInfo()) ); m_unRcvLen=0; } } } catch(char* szException) { TRACE("%s\n",szException); } catch(CString strErr) { TRACE("%s\n",strErr); GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('c'),LPARAM(&GetRevInfo()) ); m_unRcvLen=0; GetParent ()->SendMessage (WM_SEND_RECEIVE,WPARAM('E'),LPARAM(&strErr) ); } catch(...) { ; } return 0; } // The CTS (clear-to-send) signal changed state. LONG CMsgPSPWnd::OnCommCTSDetected(WPARAM wparam, LPARAM port) { if (port <= 0 || port > 4) return -1; /* CString string; string = "Clear To Send"; CString strEnter; strEnter.Insert (0,10); strEnter.Insert (0,13); m_strReceiveTxt=m_strReceiveTxt+strEnter; m_strReceiveTxt=m_strReceiveTxt+string; m_strReceiveTxt=m_strReceiveTxt+strEnter; UpdateData(FALSE); //*/ // TRACE("CCCommPLCDlg::OnCommCTSDetected()\n"); return 0; } // A break was detected on input. LONG CMsgPSPWnd::OnCommBreadDetected(WPARAM wparam, LPARAM lparam) { TRACE("CCCommPLCDlg::OnCommBreadDetected()\n"); return 0; } // The DSR (data-set-ready) signal changed state. LONG CMsgPSPWnd::OnCommDSRDetected(WPARAM wparam, LPARAM lparam) { TRACE("CCCommPLCDlg::OnCommDSRDetected()\n"); return 0; } // A line-status error occurred. Line-status errors are CE_FRAME, CE_OVERRUN, and CE_RXPARITY. LONG CMsgPSPWnd::OnCommERRDetected(WPARAM wparam, LPARAM lparam) { TRACE("CCCommPLCDlg::OnCommERRDetected()\n"); return 0; } // A ring indicator was detected. LONG CMsgPSPWnd::OnCommRingDetected(WPARAM wparam, LPARAM lparam) { TRACE("CCCommPLCDlg::OnCommRingDetected()\n"); return 0; } // The event character was received and placed in the input buffer. LONG CMsgPSPWnd::OnCommRXFlagDetected(WPARAM wparam, LPARAM lparam) { TRACE("CCCommPLCDlg::OnCommRXFlagDetected()\n"); return 0; } // The last character in the output buffer was sent. LONG CMsgPSPWnd::OnCommTXEmptyDetected(WPARAM wparam, LPARAM lparam) { TRACE("CCCommPLCDlg::OnCommTXEmptyDetected)\n"); return 0; } // The RLSD (receive-line-signal-detect) signal changed state. LONG CMsgPSPWnd::OnCommRLSDDected(WPARAM wparam, LPARAM lparam) { TRACE("CCCommPLCDlg::OnCommRLSDDected()\n"); return 0; } UINT CMsgPSPWnd::GetCalcTime() //从上次调用StartCalcTime()至目前为止的毫秒时间间隔 { if(0==m_dwStartCalcTime) //刚开始 return 0; DWORD dwEnd=::GetTickCount() ; m_nCommErrTime+=dwEnd-m_dwStartCalcTime; return dwEnd-m_dwStartCalcTime; } void CMsgPSPWnd::StartCalcTime() { m_dwStartCalcTime=::GetTickCount() ; } void CMsgPSPWnd::SendInfo(HWND hWnd,CString &strInfo) { char cInfo[100]; // sprintf(cInfo,"%s",strInfo); strcpy(cInfo,strInfo); COPYDATASTRUCT CpyData; CpyData.lpData =&cInfo[0]; CpyData.cbData =sizeof(cInfo)/sizeof(char); WPARAM wParam = (WPARAM) (HWND) m_hWnd ; // handle of sending window LPARAM lParam = (LPARAM) & CpyData; // pointer to structure with data CWnd wnd; wnd.Attach (hWnd); wnd.SendMessage(WM_COPYDATA,wParam,lParam); //不能用邮寄方式PostMessage wnd.Detach (); } BOOL CMsgPSPWnd::SetValue(const HWND hWndSend,const LPTSTR strInfo) //需要立即更新:数据操作 { //根据协议,自行修改 char cName[100]; char cValue[500]; sscanf(strInfo,"%s %s",cName,cValue); CComData * pData; POSITION pos=m_mapResource.GetStartPosition (); if(m_mapResource.Lookup(cName,(void*&)pData)) { CComData* pComData=new CComData; *pComData=*pData; pComData->m_unRegType=0x10; //只支持多个寄存器写 pComData->m_strRegValue =cValue; pComData->m_hClientWnd =hWndSend; pComData->m_pReData =GetRelation(pComData); m_listNowData.AddTail (pComData); return TRUE; } return FALSE; TRACE("CMsgPSPWnd::SetValue(%s)\n",strInfo); } void CMsgPSPWnd::SetPort(UINT portnr, UINT baud, char parity, UINT databits, UINT stopsbits,DWORD dwCommEvents,UINT nBufferSize) { m_SPData.uPortNum=portnr; m_SPData.uBaud=baud; m_SPData.cParity=parity; m_SPData.uDataBits=databits; m_SPData.uStopBits=stopsbits; m_SPData.dwCommEvents=dwCommEvents; m_SPData.nBufferSize=nBufferSize; } POSITION CMsgPSPWnd::AddData(CComData &comData) { return m_listData.AddTail(&comData); } void CMsgPSPWnd::ReadPortInf() { TRY { UINT portnr; UINT baud; char parity; UINT databits; UINT stopsbits; DWORD dwCommEvents; UINT nBufferSize; CFOData foData; m_unMemFileSize=foData.ReadPortInf( m_strAlias, portnr, baud, parity, databits, stopsbits, dwCommEvents, nBufferSize ); SetPort(portnr,baud,parity,databits,stopsbits); } CATCH( CFileException, e ) { #ifdef _DEBUG afxDump << "File could not be opened " << e->m_cause << "\n"; #endif } END_CATCH } void CMsgPSPWnd::OnTimer(UINT nIDEvent) { switch(nIDEvent) { case TIMER_EVENT_SP: { if( m_pSerialPort->InitPort(this, m_SPData.uPortNum, m_SPData.uBaud, m_SPData.cParity, m_SPData.uDataBits, m_SPData.uStopBits, m_SPData.dwCommEvents, m_SPData.nBufferSize)) { m_pSerialPort->StartMonitoring(); TRACE("*********** FIND PORT %d *********\n",m_SPData.uPortNum); } else { // port not found TRACE("***********NO FIND PORT %d *********\n",m_SPData.uPortNum); return ; } //4、启动线程 BeginThread(); KillTimer(nIDEvent); break; } case TIMER_EVENT_WM: { WriteMemData(); break; } default: { ; } } CWnd::OnTimer(nIDEvent); } void CMsgPSPWnd::WriteMemData() { // return; if(m_pMemFile) { // TRACE("CMsgPSPWnd::WriteMemFile()\n"); m_pMemFile->SeekToBegin(); //* //数据 //------------------------------------------------------------------------- //数据总记录条数 int nCount=0; // m_pMemFile->Seek(4,CFile::begin); //写数据 POSITION pos=m_listData.GetHeadPosition (); CComData* pData; try{ while(pos) { pData=(CComData*)m_listData.GetNext (pos); pData->WriteMemData (m_pMemFile); // TRACE("WriteMemData()---%d\n",m_pMemFile->GetPosition ()); nCount++; } // m_pMemFile->SeekToBegin(); // m_pMemFile->Write( &nCount,sizeof(int)); } catch(...) { TRACE("CMsgPSPWnd::WriteMemData()--Error\n"); } //------------------------------------------------------------------------- } } void CMsgPSPWnd::ReadIO() { CFOData foData; foData.SearchComData(m_strAlias,m_mapResource); Optimize(); } void CMsgPSPWnd::ReadMemData() { if(NULL==m_pMemFile) return; /* POSITION pos=m_listData.GetHeadPosition (); while(pos) { CComData comData=m_listData.GetNext (pos); comData.ReadMemData (m_pMemFile); } //*/ //创建内存文件 CreateMemFile(); } BOOL CMsgPSPWnd::CreateMemFile() { /* HANDLE CreateFileMapping( HANDLE hFile, // 映射文件的句柄, //设为0xFFFFFFFF以创建一个进程间共享的对象 LPSECURITY_ATTRIBUTES lpFileMappingAttributes, // 安全属性 DWORD flProtect, // 保护方式 DWORD dwMaximumSizeHigh, //对象的大小 DWORD dwMaximumSizeLow, LPCTSTR lpName // 必须为映射文件命名 ); //*/ /* LPVOID MapViewOfFile( HANDLE hFileMappingObject, // file-mapping object to map into // address space DWORD dwDesiredAccess, // access mode DWORD dwFileOffsetHigh, // high-order 32 bits of file offset DWORD dwFileOffsetLow, // low-order 32 bits of file offset DWORD dwNumberOfBytesToMap // number of bytes to map ); //*/ CString strFileName; strFileName.Format ("%s.mem",m_strAlias); //1、创建一个名为MySharedMem的长度为4096字节的有名映射文件: HANDLE hMySharedMapFile=CreateFileMapping((HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE, 0, 0x1000, strFileName); if(NULL==hMySharedMapFile) return FALSE; //2、并映射缓存区视图: LPSTR pszMySharedMapView=(LPSTR)MapViewOfFile(hMySharedMapFile, FILE_MAP_READ|FILE_MAP_WRITE, 0,0,0); if(NULL==pszMySharedMapView) return FALSE; //读取内存文件申请大小 ReadMDFSize(); ASSERT(0<m_unMemFileSize); //3、使其成为内存文件操作 m_pMemFile=new CMemFile((unsigned char*)pszMySharedMapView, m_unMemFileSize, 0 ); TRACE("CMsgPSPWnd::CreateMemFile()--%s--Size:%d\n",strFileName,m_unMemFileSize); // char cLen[4]; // m_pMemFile->Write( cLen,4); return TRUE; /* //客户端访问方式 //1、访问共享对象,需要获得对象名并调用OpenFileMapping函数。 HANDLE hMySharedMapFile=OpenFileMapping(FILE_MAP_WRITE, FALSE, GetIOFileName()); if(NULL==hMySharedMapFile) return; //2、并映射缓存区视图: LPSTR pszMySharedMapView=(LPSTR)MapViewOfFile(hMySharedMapFile, FILE_MAP_READ, 0,0,0); if(NULL==pszMySharedMapView) return; //3、使其成为内存文件操作 m_pMemFile=new CMemFile((unsigned char*)pszMySharedMapView, 4096, 0 ); //4、读数据 char c[100]; CString strReadTxt; m_pMemFile->SeekToBegin (); m_pMemFile->Read (&c[0],100); strcpy((LPTSTR)(LPCTSTR)strReadTxt,c); //*/ } void CMsgPSPWnd::CloseFile() { //当用户进程结束使用共享内存后,调用UnmapViewOfFile函数以取消其地址空间内的视图: if(NULL==m_pMemFile) return; LPSTR pszMySharedMapView=(LPSTR)m_pMemFile->Detach (); delete m_pMemFile; m_pMemFile=NULL; if (!UnmapViewOfFile(pszMySharedMapView)) { AfxMessageBox("could not unmap view of file"); } } void CMsgPSPWnd::ReadMDFSize() //读取内存文件大小 { CFOData foData; m_unMemFileSize=foData.ReadMDFSize (m_strAlias); } BOOL CMsgPSPWnd::IsCommErrTime() //是否在通讯错误时段内,如果在,则关闭端口,重新启动 { TRACE("CMsgPSPWnd::IsCommErrTime() m_nCommErrTimeCount=%d,m_nCommErrTime=%d\n",m_nCommErrTimeCount,m_nCommErrTime); int nCommErrTime=m_nCommErrTime; m_nCommErrTime=0; return m_nCommErrTimeCount-nCommErrTime; } bool CMsgPSPWnd::IsMoreCommErr() //可能系统通讯中断比较长或通讯失败较多,则重新建立通讯 { if(++m_unCommErr>=m_unCommErrCount) { m_unCommErr=0; if(IsCommErrTime ()>0) { return true; //要求重新建立通讯 } } return false; } bool CMsgPSPWnd::IsMoreSucceed() { if(++m_unCommSucceed>=m_unCommSucceedCount) { //多次通讯成功,清空计时错误 m_unCommErr=0; m_nCommErrTime=0; return true; } return false; } int CMsgPSPWnd::CalcuDataSize() { return 0; } bool CMsgPSPWnd::IsWaitSend() { return false; } void CMsgPSPWnd::BeginThread() { if (!(m_pThread = AfxBeginThread(RunPump,this))) return ; } void CMsgPSPWnd::Optimize() { //不做任何优化 POSITION pos=m_mapResource.GetStartPosition (); CString strKey; CComData * pData; while(pos) { m_mapResource.GetNextAssoc (pos,strKey,(void*&)pData); CComData * pComData=new CComData; *pComData=*pData; m_listData.AddTail (pComData); } } CString CMsgPSPWnd::GetHexInfo(unsigned char* pucbuf,unsigned int unLen) const { CString strBHex; CString strHex; for(UINT n=0;n<unLen;n++) { strBHex.Format (" %02x",pucbuf[n]); strHex+=strBHex; } return strHex; } CString CMsgPSPWnd::GetRevInfo() { if(m_pCurData) { CString strInfo; strInfo.Format ("%20s %s", m_pCurData->m_strAlias, GetHexInfo(&m_ucRcvTxt[0],m_unRcvLen) ); return strInfo; } return GetHexInfo(&m_ucRcvTxt[0],m_unRcvLen); } CString CMsgPSPWnd::GetSendInfo() { CString strInfo="**"; if(m_pCurData) { strInfo.Format ("%20s %s", m_pCurData->m_strAlias, GetHexInfo(&m_pCurData->m_ucProtocalTxt[0],m_pCurData->m_unDataLen) ); } else { TRACE("CMsgPSPWnd::GetSendInfo()--Error\n"); } TRACE("GetSendInfo()---%s\n",strInfo); return strInfo; } void CMsgPSPWnd::PostNcDestroy() { // TODO: Add your specialized code here and/or call the base class if(m_pThread) { // ::WaitForSingleObject(m_pThread,1000); DWORD dwExitCode=0; // TerminateThread(m_pThread,dwExitCode); // ASSERT(NULL!=TerminateThread(m_pThread->m_hThread,dwExitCode)); TerminateThread(m_pThread->m_hThread,dwExitCode); ::GetExitCodeThread(m_pThread->m_hThread,&dwExitCode); if(dwExitCode==STILL_ACTIVE) TRACE("--CMsgPSPWnd---still_active\n"); delete m_pThread; m_pThread=NULL; } CPlugPPBase::PostNcDestroy(); ReleaseResource(); } CComData* CMsgPSPWnd::GetRelation(CComData* pData)const { POSITION posOpt=m_listData.GetHeadPosition (); while(posOpt) { CComData* pComData=(CComData*)m_listData.GetNext (posOpt); if(pComData->m_nStationNum ==pData->m_nStationNum && pComData->m_unRegType ==pData->m_unRegType && (pComData->m_unRegAddr <=pData->m_unRegAddr &&pComData->m_unRegAddr+pComData->m_unRegCount>=pData->m_unRegAddr+pData->m_unRegCount) ) { return pComData; } } return NULL; } void CMsgPSPWnd::ReleaseResource() { if(m_pProtocal) { delete m_pProtocal; m_pProtocal=NULL; } if(m_pSerialPort) { delete m_pSerialPort; m_pSerialPort=NULL; } POSITION pos=m_mapResource.GetStartPosition (); CString strKey; CComData * pData; while(pos) { m_mapResource.GetNextAssoc (pos,strKey,(void*&)pData); delete pData; } m_mapResource.RemoveAll (); pos=m_listData.GetHeadPosition (); while(pos) { pData=(CComData*)m_listData.GetNext (pos); delete pData; } m_listData.RemoveAll (); CloseFile(); }